//-----------------------------------------------------------------------
// <copyright file="Create.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY 
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
// </copyright>
// <author>Andy Reeves</author>
// <email>andyr</email>
// <date>2004-03-25</date>
// <summary>Creates an Active Directory User</summary>
//-----------------------------------------------------------------------

namespace Microsoft.Sdc.Tasks.ActiveDirectory.User
{
    using System;
    using Microsoft.Build.Framework;
    using Microsoft.Build.Utilities;
    using System.Resources;
    using System.Reflection;
    using System.Xml;
    using System.Globalization;

    using AD = Microsoft.Sdc.Tasks.Configuration.ActiveDirectory;

    /// <summary>
    /// Creates an Active Directory user either locally or on a domain.
    /// </summary>
    /// <remarks>
    /// <code><![CDATA[<ActiveDirectory.User.Create UserName="userName" Password="password" DomainName="domainName" EnsureUser="ensureGroup" />]]></code>
    /// <para>where:</para>
    /// <para><i>userName (Required)</i></para>
    /// <para>The username for the Active Directory user to be created.</para>
    /// <para><i>password (Required)</i></para>
    /// <para>The password for the Active Directory user to be created.</para>
    /// <para><i>Description</i></para>
    /// <para>The description for the Active Directory user to be created.</para>
    /// <para><i>domainName</i></para>
    /// <para>The domain the group is to be added to. If not specified it defaults to the local machine.</para>
    /// <para><i>ensureUser</i></para>
    /// <para>If TRUE and the user already exists then no error is thrown and the (existing) user's password will be updated</para>
    /// </remarks>
    /// <example>
    /// <code><![CDATA[
    /// <Project>
    ///     <Target Name="Test" >
    ///         <ActiveDirectory.User.Create
    ///             UserName="newUser"
    ///             Password="123$abc"
    ///             Description="User Description"    
    ///             DomainName="mydomain"
    ///             EnsureUser="true" />
    ///     </Target>
    /// </Project>
    /// ]]></code>    
    /// </example>
    public class Create : TaskBase
    {
        private string userName;
        private string password;
        private string domainName;
        private bool ensureUser;
        private bool passwordExpires = true;
        private bool passwordExpiresSet = false;
        
        /// <summary>Private variable</summary>
        private string description;

        /// <summary>
        /// Initializes a new instance of the Create class.
        /// </summary>
        public Create()
        {
        }       
        
        /// <summary>
        /// The password for the new user.
        /// </summary>
        /// <value>The new user's password</value>
        [Required]
        public string Password
        {
            get
            {
                return (this.password == null ? String.Empty : this.password);
            }

            set
            {
                this.password = value;
            }
        }

        /// <summary>
        /// The username for the new user.
        /// </summary>
        /// <value>The new user's username</value>
        [Required]
        public string UserName
        {
            get
            {
                return (this.userName == null ? String.Empty : this.userName);
            }

            set
            {
                this.userName = value;
            }
        }

        /// <summary>
        /// The domain to which the new Active Directory user is to be added.
        /// </summary>
        /// <value>The name of the domain to which the new user is to be added. If not specified it defaults to the local machine</value>
        public string DomainName
        {
            get
            {
                return (this.domainName == null ? String.Empty : this.domainName);
            }

            set
            {
                this.domainName = value;
            }
        }

        /// <summary>
        /// A description for the user.
        /// </summary>
        public string Description
        {
            get { return this.description; }
            set { this.description = value; }
        }

        /// <summary>
        /// If TRUE and the User is already in the domain no error is thrown, in which case the user's password will be updated.
        /// </summary>
        /// <value>True to not throw an error if the user is already in the domain.</value>
        public bool EnsureUser
        {
            get
            {
                return this.ensureUser;
            }

            set
            {
                this.ensureUser = value;
            }
        }

        /// <summary>
        /// Set to FALSE to set the equivalent of "password never expires".
        /// </summary>
        /// <value>Defaults to true to be backwordly compatible</value>
        public bool PasswordExpires
        {
            get
            {
                return this.passwordExpires;
            }

            set
            {
                this.passwordExpiresSet = true;
                this.passwordExpires = value;
            }
        }

        /// <summary>
        /// Performs the action of this task.
        /// </summary>
        protected override void InternalExecute()
        {
            #region Execute code

            if (AD.User.Exists(this.userName, this.domainName))
            {
                if (this.ensureUser)
                {
                    Log.LogMessageFromResources(MessageImportance.Low, "ActiveDirectory.UserExistsUpdatingPassword");

                    // Update the password
                    AD.User user = AD.User.Load(this.userName, this.domainName);
                    user.Password = this.password;
                    // only change the password flag if it has been set by script
                    if (this.passwordExpiresSet) user.PasswordExpires = this.passwordExpires;
                    if (!string.IsNullOrEmpty(this.description))
                    {
                        user.Description = this.description;
                    }
                    user.Save();
                }
                else
                {
                    throw new TaskException("ActiveDirectory.UserExists", this.userName);
                }
            }
            else
            {
                Log.LogMessageFromResources("ActiveDirectory.CreatingUser", this.userName);
                AD.User user = new AD.User(this.userName, this.password, this.domainName);
                if (!string.IsNullOrEmpty(this.description))
                {
                    user.Description = this.description;
                }
                user.PasswordExpires = this.passwordExpires;
                user.Save();
            }
            #endregion
        }
    }
}